package com.smartwebx.ha.dal.util.aspect;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Set;

import org.apache.ibatis.annotations.Param;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.smartwebx.ha.dal.config.StatGroupThreadLocal;

/**
 * 在 db 层调用 realtime 、feature 特定方法之前对站码进行过滤
 * 
 * @author zhangxi
 * 
 */
@Component
@Aspect
@Order(value = 1)
public class StcdGroupsFilterBefore {
	/**
	 * 拦截 db 层下 realtime、feature 包下的所有方法
	 * 
	 * @param jp
	 * @param stcds
	 * @return
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	@Around("execution(* com..dal.realtime.dao.*.*(..)) || execution(* com..dal.feature.dao.*.*(..))")
	public Object doArounBeforeByStcds(ProceedingJoinPoint jp) throws Throwable {
		MethodSignature msig = (MethodSignature) jp.getSignature();
		// 获得所有方法的所有参数的注解
		Annotation[][] paramsAnnot = msig.getMethod().getParameterAnnotations();
		int pointKeyIndex = this.checkPointParamIndex(paramsAnnot);
		if (pointKeyIndex != -1 && StatGroupThreadLocal.getInWeb()) {
			Set<String> statGroups = StatGroupThreadLocal.getStatGroups();
			
			if(statGroups == null){
				statGroups = Sets.newHashSet();
			}
			statGroups.add("62911675");
			statGroups.add("50916500");
			statGroups.add("62911676");
			statGroups.add("42000000");
			Object[] args = jp.getArgs();
			Object findArg = args[pointKeyIndex];
			if (findArg instanceof String) { // 站码
				String stcd = (String) findArg;
				if (statGroups.contains(stcd)) {
					return jp.proceed();
				} else {
					throw new Exception("所传递的站码不在当前用户的站群列中");
				}
			} else if (findArg instanceof Collection<?>) {// 站群码
				Iterable<String> stcds = (Iterable<String>) findArg;
				Set<String> postStcds = Sets.newHashSet(stcds);
				SetView<String> filterPostStcds = Sets.intersection(postStcds,
						statGroups);
				if (!postStcds.isEmpty()&&filterPostStcds.isEmpty()) {
					throw new Exception("所传递的站群码都不在当前用户的站群列中");
				} else {
					args[pointKeyIndex] = Lists.newArrayList(filterPostStcds);
					return jp.proceed(args);
				}
			} else {
				throw new Exception("所传入的站群/站码类型错误");
			}
		} else {
			return jp.proceed();
		}
	}

	private int checkPointParamIndex(Annotation[][] paramsAnnot) {
		String stcd = "stcd";
		String stcds = "stcds";
		int curIndex = -1;
		boolean isFind = false;
		out: for (Annotation[] paramAnnots : paramsAnnot) {
			curIndex++;
			for (Annotation paramAnnot : paramAnnots) {
				if (paramAnnot instanceof Param) {
					Param ibatisParam = (Param) paramAnnot;
					if (Objects.equal(ibatisParam.value(), stcd)
							|| Objects.equal(ibatisParam.value(), stcds)) {
						isFind = true;
						break out;
					}
				}
			}
		}

		return isFind ? curIndex : -1;
	}
}
